package fr.bludwarf.skywarrior.ile;

import fr.bludwarf.skywarrior.exceptions.ConstructionImpossible;
import fr.bludwarf.skywarrior.exceptions.EvenementInconnuOublie;
import fr.bludwarf.skywarrior.global.Temps;
import fr.bludwarf.skywarrior.global.TimeFactorInconnu;
import fr.bludwarf.skywarrior.joueur.Joueur;
import fr.bludwarf.skywarrior.joueur.Ressources;
import fr.bludwarf.skywarrior.joueur.TypeUnite;
import fr.bludwarf.skywarrior.utils.TimeUtils;

public class Construction {
	
	/** Unité en cours de construction */
	TypeUnite _unite = null;
	
	/** Ile concernée */
	final EtatIle _etatIle;
	
	/** Durée de construction restante */
	double _tempsRestant;
	
	/** La construction a été commencée ? (ressource déjà dépensées) */
	boolean _commencee = false;
	
	public Construction(final EtatIle etatIle, final TypeUnite unite) throws TimeFactorInconnu {
		_etatIle = etatIle;
		_unite = unite;
		_tempsRestant = getDureeEstimee();
	}
	
	public double getDureeEstimee() throws TimeFactorInconnu
	{
		// Est-ce qu'il y a un architecte ou au moins un architecte prévu avant cette construction ?
		boolean architecte = false;
		if (_etatIle.getNb(TypeBatiment.ARCHITECTE) == 1 || _etatIle.getNbPrevuAvant(TypeBatiment.ARCHITECTE, this) >= 1)
		{
			architecte = true;
		}
		return _unite.getDuree() * Temps.getTimeFactor(_unite.getClass(), _etatIle.pop(), architecte);
	}
	
	/**
	 * Recopie
	 * @param construction
	 */
	public Construction(Construction construction, EtatIle etatIle) {
		_etatIle = etatIle;
		_unite = construction._unite;
		_tempsRestant = construction._tempsRestant;
		_commencee = construction._commencee;
	}

	/**
	 * @return la quantité de ressource utilisées pour commencer la construction
	 * @since 2 nov. 2011
	 */
	public Ressources commencer()
	{
		_commencee = true;
		return _unite.getCout();
	}
	
	@Override
	public String toString() {
		return (_commencee ? "*" : "") + _unite + "(" + TimeUtils.timeToString(_tempsRestant) + ")";
	}
	
	public double getTempsRestant()
	{
		return _tempsRestant;
	}

	/**
	 * @param temps
	 * @return le temps qui n'a pas été utilisé dans la construction (peut être utilisé pour la construction suivante), 0 si aucun temps restant
	 * @throws ConstructionImpossible si le bâtiment n'a pas été commencé
	 * @throws EvenementInconnuOublie 
	 * @since 8 nov. 2011
	 */
	public double construire(final double temps) throws ConstructionImpossible, EvenementInconnuOublie {
		// La construction a été commencée ?
		if (!_commencee)
		{
			throw new ConstructionImpossible("Le bâtiment " + this + " n'a pas été commencé");
		}
		
		// Temps qu'il resta en rab après la construction
		double rab = 0;
		try
		{
			Temps.decrementer(temps, _tempsRestant);
		}
		catch (final EvenementInconnuOublie e)
		{
			rab = 0;
		}
		
		// On continue la construction
		_tempsRestant = Temps.decrementer(_tempsRestant, temps);
		
		if (rab > 0)
		{
			System.err.println("Il ne devrait pas rester de rab pour la construction " + this);
		}
		
		return rab;
	}
	
	public boolean estTerminee()
	{
		return _tempsRestant <= 0;
	}

	public TypeUnite getUnite() {
		return _unite;
	}

	public Ile getIle() {
		return _etatIle.getIle();
	}
	
	public Ressources getCout()
	{
		return _unite.getCout();
	}
	
	public boolean aEteCommencee()
	{
		return _commencee;
	}
	
	public Joueur getJoueur()
	{
		return _etatIle.getIle().getJoueur();
	}

	/**
	 * Recalcule le temps restant d'une construction <b>non commencée</b>
	 * @throws TimeFactorInconnu
	 * @since 15 nov. 2011
	 */
	public void recalculerTempsRestant() throws TimeFactorInconnu {
		if (!_commencee)
		{
			_tempsRestant = getDureeEstimee();
		}
	}

	public int getCoutPop() {
		return _unite.pop();
	}

	public void applyTimeFactor(final double timeFactor) {
		_tempsRestant *= timeFactor;
	}
	
}
